#pragma once

#include <iostream>
#include <memory>
#include <sys/epoll.h>
#include "Socket.hpp"
#include "Epoller.hpp"
#include "Log.hpp"
#include "nocopy.hpp"

static const int num = 64;

uint32_t EVENT_IN = EPOLLIN;
uint32_t EVENT_OUT = EPOLLOUT;

class EpollServer : public NoCopy
{
public:
    EpollServer(uint16_t port):m_port(port), m_listenSockPtr(new Sock()), m_epollerPtr(new Epoller())
    {}

    void init()
    {
        m_listenSockPtr->Socket();
        m_listenSockPtr->Bind(m_port);
        m_listenSockPtr->Listen();

        log(INFO, "create listen socket success: %d", m_listenSockPtr->Fd());
    }

    void start()
    {
        // 1、首先将m_listenSock添加到epoll中，本质是将listenSock和它关心的事件，添加到内核epoll模型中的红黑树中。
        m_epollerPtr->EpollerUpdate(EPOLL_CTL_ADD, m_listenSockPtr->Fd(), EVENT_IN);
        struct epoll_event revs[num];
        for(;;)
        {
            int n = m_epollerPtr->EpollerWait(revs, num);
            if(n > 0)
            {
                // 有事件就绪
                log(DEBUG, "event happened, fd is: %d", revs[0].data.fd);
                // HandlerEvent(revs, n);
            }
            else if(0 == n)
            {
                log(INFO, "time out...");
            }
            else{
                log(ERROR, "epoll wait error");
            }
        }
    }

    ~EpollServer()
    {
        m_listenSockPtr->Close();
    }
private:
    std::shared_ptr<Sock> m_listenSockPtr;
    std::shared_ptr<Epoller> m_epollerPtr;
    uint16_t m_port;
};